package com.quaint.poster.core.impl;

import com.quaint.poster.annotation.PosterBackground;
import com.quaint.poster.annotation.PosterFontCss;
import com.quaint.poster.annotation.PosterImageCss;
import com.quaint.poster.core.abst.Poster;
import com.quaint.poster.core.decorators.BackgroundDecorator;
import com.quaint.poster.core.decorators.ImageDecorator;
import com.quaint.poster.core.decorators.TextDecorator;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 基础海报功能（带文字和图片）
 * @author naiqing
 * 20 Jan 2022
 * @since 1.0
 */
public abstract class BasePosterImpl<E> implements PosterTemplate<E> {
    /**
     * 如果设置了默认字体，则覆盖”宋体“
     */
    private Font defaultFont = new Font(null);
    /**
     * 此海报用到的全部字体，如果为空时则使用默认字体
     */
    private final Map<String, Font> fontMap = new HashMap<>();


    /**
     * 设置海报全文的默认字体
     *
     * @param defaultFont 字体
     */
    public BasePosterImpl defaultFont(Font defaultFont) {
        this.defaultFont = defaultFont;
        fontMap.putIfAbsent(defaultFont.getFontName(), defaultFont);
        return this;
    }

    /**
     * 安装海报用到的全部字体
     *
     * @param fonts 字体库集合
     */
    public BasePosterImpl installFonts(Font... fonts) {
        for (int i = 0; fonts != null && i < fonts.length; i++) {
            fontMap.putIfAbsent(fonts[i].getFontName(), fonts[i]);
        }
        return this;
    }

    @Override
    public Poster annotationDrawPoster(E content) throws IllegalAccessException {
        // 初始化背景画板
        Poster finalDraw = backPoster(content);
        // 反射获取所有属性
        Field[] fields = content.getClass().getDeclaredFields();
        // 给背景绘制基本属性
        for (Field field : fields) {
            field.setAccessible(true);
            //获取属性值
            Object value = field.get(content);
            PosterFontCss posterFontCss = field.getAnnotation(PosterFontCss.class);
            if (posterFontCss != null && value instanceof String) {
                finalDraw = drawTextImpl(finalDraw, (String) value, posterFontCss);
            }
            PosterImageCss posterImageCss = field.getAnnotation(PosterImageCss.class);
            if (posterImageCss != null && value instanceof BufferedImage) {
                finalDraw = drawImageImpl(finalDraw, (BufferedImage) value, posterImageCss);
            }
            Poster appendPosterDecorator = appendDecorator(finalDraw, field, value);
            if(appendPosterDecorator != null){
                finalDraw = appendPosterDecorator;
            }
        }
        return finalDraw;
    }

    /**
     * 用于扩展更多支持的画板
     *
     * @param base 原画板对象（默认只支持文字和图像）
     * @param field  对字段的处理
     * @param value   字段对应的值
     * @return 追加后的画板对象
     */
    protected abstract Poster appendDecorator(Poster base, Field field, Object value);

    /**
     * 初始化背景画板
     *
     * @param content 类对象
     * @throws IllegalAccessException
     */
    private Poster backPoster(E content) throws IllegalAccessException {
        // 反射获取所有属性
        Field[] fields = content.getClass().getDeclaredFields();
        //获取背景注解
        Field bgField = Arrays.stream(fields).filter(s -> s.getAnnotation(PosterBackground.class) != null).findFirst()
                .orElseThrow(() -> new RuntimeException("@PosterBackground背景注解标记不可为空！"));
        //设置属性可被访问
        bgField.setAccessible(true);
        Object bgContentObj = bgField.get(content);
        // 最后需要执行绘制方法的类
        Poster finalDraw;
        if (bgContentObj instanceof BufferedImage) {
            BufferedImage bg = (BufferedImage) bgContentObj;
            PosterBackground bgAnn = bgField.getAnnotation(PosterBackground.class);
            finalDraw = new BackgroundDecorator().toBuilder()
                    .bgImage(bg)
                    .width(bgAnn.width())
                    .height(bgAnn.height())
                    .build();
        } else {
            throw new RuntimeException("@PosterBackground背景注解标记的类型需要为BufferedImage！");
        }
        return finalDraw;
    }

    /**
     * 绘制文本装饰器
     *
     * @param base 基础图片
     * @param text 要绘制的文本
     * @return poster
     */
    private Poster drawTextImpl(Poster base, String text, PosterFontCss ann) {
        if (ann == null) {
            return base;
        }
        TextDecorator.TextDecoratorBuilder content = new TextDecorator(base).toBuilder()
                .positionX(ann.position()[0])
                .positionY(ann.position()[1])
                .fontSize(ann.size())
                .fontStyle(ann.style())
                .canNewLine(ann.canNewLine()[0] == 1)
                .width(ann.canNewLine()[1])
                .delLine(ann.delLine())
                .newLineLimit(ann.canNewLine()[2])
                .color(new Color(ann.color()[0], ann.color()[1], ann.color()[2]))
                .lineHeight(ann.lineHeight())
                .content(text);
        //获取注解中的字体
        if (ann.name() != null && !ann.name().isEmpty()) {
            content.font(fontMap.getOrDefault(ann.name(), defaultFont));
        }
        return content.build();
    }

    /**
     * 绘制图片装饰器
     *
     * @param base  基础图片
     * @param image 要绘制的图片
     * @return poster
     */
    private Poster drawImageImpl(Poster base, BufferedImage image, PosterImageCss ann) {
        if (ann == null) {
            return base;
        }
        return new ImageDecorator(base).toBuilder()
                .positionX(ann.position()[0])
                .positionY(ann.position()[1])
                .width(ann.width())
                .height(ann.height())
                .circle(ann.circle())
                .radius(ann.radius())
                .image(image)
                .build();
    }
}
